home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
archiver
/
zipvinc.zip
/
ZIPV.C
< prev
next >
Wrap
C/C++ Source or Header
|
1989-02-15
|
17KB
|
679 lines
/******************************************************************************
*
*
* ZIPV -- SHARE compatible ZIP file list utility.
*
*
* This code was written as a demonstration of how to read
* the ZIP file format. It does not attempt to support
* ZIP files which span multiple diskettes (it is not even
* clear to me how that would be done). It does support
* multiple ZIP file names on the command line and does
* support wildcards. Under DOS 3.0 or above all files are
* opened in SHARE compatible mode.
*
* The output format is patterned after (stolen from) Vern
* Buerg's ARCV format.
*
*
* It appears that there are two ways to extract the names
* of files contained in a ZIP file. One copy is kept in a
* "local file header" which proceeds the compressed file. The
* other copy is kept in the "central directory". The notes
* that accompany PKZIP are not clear whether or not these
* will always agree. I chose to read the information from
* the central directory, even though I have to read past
* all of the local file headers to get there.
*
* This code is placed in the public domain. You may do whatever
* you like with it.
*
* Ken Brown
*
*
*
*
* Syntax:
*
* ZIPV file_spec1[.ZIP] [file_spec2[.ZIP] ...]
*
*
*
******************************************************************************
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <bios.h>
#include <dos.h>
#include <io.h>
#include <share.h>
#include <fcntl.h>
/* These structures must be byte aligned */
#pragma pack(1)
/* Structure of the local file header */
struct LOCAL_HEADER {
long Signature;
int Version;
int BitFlag;
int CompressionMethod;
int FileTime;
int FileDate;
long CRC32;
long CompressedSize;
long UnCompressedSize;
int FileNameLength;
int ExtraFieldLength;
};
/* Structure of the central directory record */
struct CENTRAL_RECORD {
long Signature;
int VersionMadeBy;
int VersionNeeded;
int BitFlag;
int CompressionMethod;
int FileTime;
int FileDate;
long CRC32;
long CompressedSize;
long UnCompressedSize;
int FileNameLength;
int ExtraFieldLength;
int CommentFieldLength;
int DiskStartNumber;
int InternalAttributes;
long ExternalAttributes;
long LocalHeaderOffset;
};
#pragma pack()
/*
* This structure will be used to build a list of files
* from a wildcard file_spec.
*
*/
struct FILELIST {
char FileName[83];
struct FILELIST *NextFile;
}
/* Global variables */
struct FILELIST *FileList,
*FilePtr;
static int TotalFiles;
static long TotalBytes;
static long TotalUnCompressedBytes;
/* Function prototypes */
extern int main(int argc,char * *argv);
extern int ProcessFile(char *ZipFileName);
extern int ListZipFile(char *ZipFileName);
extern int DisplayHeaderRecord(struct CENTRAL_RECORD CentralDirRecord,char *FileName);
extern int DisplayTotals(void );
extern char *DisplayCompressionType(int Compression);
extern char *DisplayMonthName(int Month);
extern int BuildFileList(char *FileMask);
main(int argc, char *argv[])
{
int Counter;
char ZipFileName[83],
*StrPtr;
if(argc < 2) {
printf("Syntax: ZIPV file_spec1[.ZIP] [file_spec2[.ZIP] ...]\n");
exit(1);
}
for(Counter = 1; Counter < argc; Counter++) {
if(strlen(argv[Counter]) > 82) {
printf("Syntax: ZIPV file_spec1[.ZIP] [file_spec2[.ZIP] ...]\n");
exit(1);
}
strcpy(ZipFileName,argv[Counter]);
strupr(ZipFileName);
/* If the .ZIP extension is missing add it. */
if(strchr(ZipFileName,'.') == NULL) {
strcat(ZipFileName,".ZIP");
}
ProcessFile(ZipFileName);
}
exit(0);
}
/* Process each command line argument (may contain a wildcard). */
ProcessFile(char *ZipFileName)
{
FileList = NULL;
/* Build a list of file names matching the file_spec. */
BuildFileList(ZipFileName);
/* If FileList == NULL no matching files were found. */
if(FileList == NULL) {
if(strchr(ZipFileName,'*') == NULL && strchr(ZipFileName,'?') == NULL) {
printf("File not found: %s\n\n",ZipFileName);
}
else {
printf("No matching files found: %s\n\n",ZipFileName);
}
}
else {
FilePtr = FileList;
while(FilePtr != NULL) {
ListZipFile(FilePtr->FileName);
FilePtr = FilePtr->NextFile;
}
}
return 0;
}
ListZipFile(char *ZipFileName)
{
int ZipFileHandle,
BytesRead;
long FileOffset;
char *FileName,
*ReadPtr;
struct LOCAL_HEADER LocalFileHeader;
struct CENTRAL_RECORD CentralDirRecord;
/* Open the ZIP file. Use sopen() if possible. */
if(_osmajor >= 3) {
ZipFileHandle = sopen(ZipFileName,O_RDONLY|O_BINARY,SH_DENYWR);
if(ZipFileHandle == -1) {
printf("File is currently locked, cannot open: %s\n\n",ZipFileName);
return 0;
}
}
else {
ZipFileHandle = open(ZipFileName,O_RDONLY|O_BINARY);
if(ZipFileHandle == -1) {
printf("Cannot open: %s\n\n",ZipFileName);
return 0;
}
}
printf("ZIP File: %s\n",ZipFileName);
printf("\n");
TotalFiles = 0;
TotalBytes = 0L;
TotalUnCompressedBytes = 0L;
printf("Name Length Stowage SF Size now Date Time CRC \n");
printf("============ ======== ======== ==== ======== ========= ====== ========\n");
/* Read the signature from the first local header */
BytesRead = read(ZipFileHandle,(char *)&LocalFileHeader,sizeof(long));
if(BytesRead != sizeof(long)) {
printf("Not a ZIP file\n\n");
close(ZipFileHandle);
return 0;
}
if(LocalFileHeader.Signature != 0x04034b50) {
printf("Not a ZIP file\n\n");
close(ZipFileHandle);
return 0;
}
/* Skip over all of the compressed files and get to the central
directory */
while(1) {
ReadPtr = (char *)&LocalFileHeader;
ReadPtr += 4;
/* Read the remainder of the local file header (we already read
the signature. */
BytesRead = read(ZipFileHandle,ReadPtr,sizeof(struct LOCAL_HEADER)-4);
if(BytesRead != sizeof(struct LOCAL_HEADER) - 4) {
printf("Invalid ZIP file format\n\n");
close(ZipFileHandle);
return 0;
}
FileOffset = LocalFileHeader.FileNameLength +
LocalFileHeader.ExtraFieldLength +
LocalFileHeader.CompressedSize;
/* Jump to the next local file header */
if(lseek(ZipFileHandle,FileOffset,SEEK_CUR) == -1) {
printf("Invalid ZIP file format\n\n");
close(ZipFileHandle);
return 0;
}
/* Read the next signature */
BytesRead = read(ZipFileHandle,(char *)&LocalFileHeader,sizeof(long));
if(BytesRead != sizeof(long)) {
printf("Invalid ZIP file format\n\n");
close(ZipFileHandle);
return 0;
}
/* If we get a match we have found the beginning of the central
directory. */
if(LocalFileHeader.Signature == 0x02014b50) {
break;
}
}
CentralDirRecord.Signature = LocalFileHeader.Signature;
/* Read the records in the central directory one at a time */
while(1) {
/* Read the remainder of the file header record (we already
have the signature. ReadPtr points into CentralDirRecord
4 bytes from the beginning (right behind the signature. */
ReadPtr = (char *)&CentralDir